package util

import compound.repository.ConvertService
import compound.repository.LookupService
import compound.repository.entries.DBLinks
import compound.repository.entries.Synonym
import edu.ucdavis.genomics.metabolomics.binbase.annotations.AnnotationHelper
import edu.ucdavis.genomics.metabolomics.binbase.annotations.QueryObject

/**
 * Created by IntelliJ IDEA.
 * User: wohlgemuth
 * Date: Apr 27, 2010
 * Time: 8:11:42 PM
 * To change this template use File | Settings | File Templates.
 */
class ConvertHelper {

  def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()

  /**
   * index over the required keys
   */
  private Map<String, String> methodFromNames = new HashMap<String, String>()

  /**
   * index over the required keys
   */
  private Map<String, String> methodToNames = new HashMap<String, String>()

  /**
   * internal instance
   */
  private static ConvertHelper instance = null

  private ConvertHelper() {

    //contains all possible froms
    Collection<QueryObject> fromSet = AnnotationHelper.getQueryableAnnotations(LookupService.class)

    //contains all possible tos
    Collection<QueryObject> toSet = AnnotationHelper.getQueryableAnnotations(ConvertService.class)

    //generate our lookup association
    for (QueryObject q: fromSet) {
      methodFromNames.put(q.annotation.name().toLowerCase(), q.getMethod().getName())
    }

    //generate our lookup association
    for (QueryObject q: toSet) {
      methodToNames.put(q.annotation.name().toLowerCase(), q.getMethod().getName())
    }
  }

  /**
   * returns the instance
   * @return
   */
  public static ConvertHelper getInstance() {
    if (instance == null) {
      instance = new ConvertHelper()
    }

    return instance
  }
  /**
   * from what can we convert
   */
  Collection getFromConversions() {
    return getOptionList(methodFromNames.keySet().sort())
  }

  /**
   * get to conversions
   */
  Collection getToConversions() {
    return getOptionList(methodToNames.keySet().sort())
  }

  /**
   * gets the from method name
   * @param from
   * @return
   */
  String getFromMethodName(String from) {
    return methodFromNames.get(from)
  }

  /**
   * gets the to method name
   * @param to
   * @return
   */
  String getToMethodName(String to) {
    return methodToNames.get(to)
  }

  /**
   * Generate the option list
   */
  private Collection getOptionList(def data) {
    def list = new ArrayList();
    def map = [:]
    data.each {String s ->
      map = new HashMap()
      map.put("ID", s)
      map.put("VALUE", g.message(code: s, default: s, encodeAs: "HTML"))
      list.add(map)
    }
    //println list
    return list
  }


  public Collection<String> getFromIdentifiers() {
    def result = []

    for (Object e in methodFromNames.keySet().sort()) {
      result.add e.toString()
    }


    return result
  }

  public def getToIdentifiers() {
    def result = []

    for (Object e in methodToNames.keySet().sort()) {
      result.add e.toString()
    }


    return result
  }

  /**
   * split prefix data
   * @param keyname
   * @param inputData
   * @return
   */
  public String splitPreeFix(String keyname, def inputData) {
    String resultStr = "";
    if (inputData != null) {
      if (inputData instanceof Collection) {
        if (inputData.size() > 0) {
          if (keyname.toString().equalsIgnoreCase("links")) {
            inputData.each { s ->

              if (resultStr.length() == 0) {
                resultStr = s.toString()
              }
              else {
                resultStr = resultStr + ", " + toString(s)
              }

            }

          } else {

            inputData.each { s ->

              def res = s.toString().split(":")
              if (resultStr.length() == 0) {
                if (res.length > 0) {
                  resultStr = res[1] ? res[1] : res[0]
                }
                else {
                  resultStr = res
                }
              }
              else {
                if (res.length > 0) {
                  resultStr = resultStr + ", " + (res[1] ? res[1] : res[0])
                }
                else {
                  resultStr = resultStr + ", " + res
                }
              }

            }

          }
        }
      } else {

        resultStr = inputData.toString();
      }
    }

    return resultStr;
  }

  /**
   * converts a given value to a string
   * @param
   value
   * @return
   */
  public String toString(def cval) {

    if (cval instanceof DBLinks) {
      return cval.linkID
    }
    else if (cval instanceof Synonym) {
      return cval.name
    }
    else {
      if (cval instanceof Collection) {
        Collection result = new HashSet()

        cval.each {def v ->
          result.add(toString(v))
        }

        return result.toString()
      }
      else {
        return cval.toString()
      }
    }
  }

}
